<?php

App::uses('AppModel', 'Model');

/**
 * CakePHP OrganisationNotification
 * 
 * @author Francis Adu-Gyamfi <francis.adu-gyamfi@matrixdesigns.org>
 */
class OrganisationNotification extends AppModel {

    public $useDbConfig = "organisations";

    /**
     * belongsTo associations
     *
     * @var array
     */
    public $belongsTo = array(
        'Organisation' => array(
            'className' => 'Organisation',
            'foreignKey' => 'organisation_id',
            'conditions' => '',
            'fields' => '',
            'order' => ''
        ),
        'NotificationType' => array(
            'className' => 'NotificationType',
            'foreignKey' => 'notification_type_id',
            'conditions' => '',
            'fields' => '',
            'order' => ''
        )
    );
    
    public $hasMany = array(
        'OrganisationNotificationParam' => array(
            'className' => 'OrganisationNotificationParam',
            'foreignKey' => 'organisation_notification_id',
            'conditions' => '',
            'fields' => '',
            'order' => ''
        )
    );
    
    private function getGroupableNotifications($organisation_id, $read) {
        $conditions = array(
            'OrganisationNotification.active' => 1,
            'OrganisationNotification.organisation_id' => $organisation_id,
            'NotificationType.groupable' => 1,
            'OrganisationNotification.created > DATE_SUB(NOW(), INTERVAL 1 WEEK) ',
            'NOT' => array('OrganisationNotification.target_id' => null)
        );

        if (in_array($read, array(0, 1))) {
            $conditions['OrganisationNotification.read'] = $read;
        }

        $data = $this->find('all', array(
            'fields' => array(
                'MIN(OrganisationNotification.read) as ntf_read',
                'MAX(OrganisationNotification.created) as ntf_dt',
                'MAX(OrganisationNotification.id) as ntf_id ', 
                'OrganisationNotification.id', 
                'OrganisationNotification.organisation_id', 
                'OrganisationNotification.notification_type_id',
                'OrganisationNotification.target_id',
                'Organisation.slug', 'NotificationType.*'
            ),
            'conditions' => $conditions,
            'order' => array(
                'OrganisationNotification.id' => 'desc',
                'OrganisationNotification.read' => 'asc'
            ),
            'group' => array(
                'OrganisationNotification.notification_type_id', 
                'DATE(OrganisationNotification.created)',
                'OrganisationNotification.target_id'
            )
        ));
        
        return $data;
    }
    
    private function getNonGroupedNotifications($organisation_id, $read) {
        $conditions = array(
            'OrganisationNotification.active' => 1,
            'OrganisationNotification.organisation_id' => $organisation_id,
            'NotificationType.groupable' => 0,
            'OrganisationNotification.created > DATE_SUB(NOW(), INTERVAL 1 WEEK) '
        );

        if (in_array($read, array(0, 1))) {
            $conditions['OrganisationNotification.read'] = $read;
        }

        $data = $this->find('all', array(
            'conditions' => $conditions,
            'order' => array(
                'OrganisationNotification.id' => 'desc',
                'OrganisationNotification.read' => 'asc'
            )
        ));
        
        return $data;
    }

    public function getList($organisation_id, $read = -1, $limit = 10, $offset = 0) {
        
        $groupable = $this->getGroupableNotifications($organisation_id, $read);
        $nongrp = $this->getNonGroupedNotifications($organisation_id, $read);
        
        $data = array_merge($groupable, $nongrp);
        
        $list = array();

        foreach ($data as $d) {
            $org_slug = $d['Organisation']['slug'];
            $url = str_replace("{org_slug}", $org_slug, $d['NotificationType']['url']);
            $d['OrganisationNotification']['url'] = $url . "?ntf_grp=" . $d['NotificationType']['id'] . "&ntf_id=" . $d['OrganisationNotification']['id'];
            $d['OrganisationNotification']['read'] = isset($d[0]['ntf_read']) ? $d[0]['ntf_read'] : $d['OrganisationNotification']['read'];
            $d['OrganisationNotification']['created'] = isset($d[0]['ntf_dt']) ? $d[0]['ntf_dt'] : $d['OrganisationNotification']['created'];
 
            $d['OrganisationNotification']['message'] = $this->updateTemplateText(
                    $d['NotificationType']['template'], 
                    $d['OrganisationNotification']['notification_type_id'], 
                    $d['OrganisationNotification']['created'],
                    $d['OrganisationNotification']['target_id']);
              

            $list[] = $d['OrganisationNotification'];
        }

        return $list;
    }

    private function updateTemplateText($template, $notification_type_id, $ntf_dt, $target_id) {       
        
        $ntf_params = $this->OrganisationNotificationParam->find('all', array(
            'fields' => array(
                'OrganisationNotificationParam.key',
                'GROUP_CONCAT(DISTINCT(OrganisationNotificationParam.value)) as vals'
            ),
            'conditions' => array(
                'OrganisationNotification.notification_type_id' => $notification_type_id,
                'OrganisationNotification.target_id' => $target_id,
                'DATE(OrganisationNotificationParam.created)' => date('Y-m-d', strtotime($ntf_dt))
            ),
            'group' => array(
                'OrganisationNotificationParam.key'
            ),
            'order' => array('OrganisationNotificationParam.id' => 'desc')
        ));
        
        foreach($ntf_params as $param) {
            $key = "{" . $param['OrganisationNotificationParam']['key'] . "}";
            $value = "";
            $val_group = explode("," , $param[0]['vals']);
            
            if ( count($val_group) > 2) {
                $remaining = count($val_group) - 2;
                $names = implode(", ", array("<b>{$val_group[0]}</b>", "<b>{$val_group[1]}</b>"));
                $value = "{$names} and <b>{$remaining} others</b>";
            } else if( count($val_group) == 2 ) {
                $names = implode(" and ", array("<b>{$val_group[0]}</b>", "<b>{$val_group[1]}</b>"));
                $value = "{$names}";
            }
            else {
                $value = "<b>{$val_group[0]}</b>";
            }
            
            $template = str_replace($key, $value, $template);
        }
        
        return $template;
    }

    public function add($organisation_id, $type_name, $params = array()) {
        $this->create();

        $type = $this->NotificationType->find('first', array(
            'conditions' => array('NotificationType.name' => $type_name),
            'recursive' => -1
        ));

        if (!$type) {
            return;
        }
        
        $data = array(
            'OrganisationNotification' => array(
                'organisation_id' => $organisation_id,
                'notification_type_id' => $type['NotificationType']['id'],
                'source_id' => isset($params['source_id']) ? $params['source_id'] : null,
                'target_id' => isset($params['target_id']) ? $params['target_id'] : null
            ),
            'OrganisationNotificationParam' => array()
        );
        
        // clean up non parameter data
        unset($params['source_id']);
        unset($params['target_id']);

        // create notification template parameters
        if( is_array($params) ) {
            foreach($params as $key => $value) {
                $data['OrganisationNotificationParam'][] = array(
                    'key' => $key,
                    'value' => $value
                );
            }
        }

        $saved = $this->saveAll($data, array('deep' => true));

        return $saved;
    }

    public function markGroupRead($organisation_id, $notification_type_id, $read = 1) {
        $this->updateAll(array(
            'OrganisationNotification.read' => $read
        ), array(
            'OrganisationNotification.organisation_id' => $organisation_id,
            'OrganisationNotification.notification_type_id' => $notification_type_id
        ));

        return array('status' => 'success', 'notification_type_id' => $notification_type_id, 'read' => $read);
    }
    
    public function markRead($organisation_id, $notification_type_id, $notification_id, $read = 1) {
        $type = $this->NotificationType->find('first', array(
            'conditions' => array(
                'NotificationType.id' => $notification_type_id
            ),
            'recursive' => -1
        ));
        
        if( $type && $type['NotificationType']['groupable'] == 1 ) {
            return $this->markGroupRead($organisation_id, $notification_type_id, $read);
        }
        
        else {
            $this->updateAll(array(
                'OrganisationNotification.read' => $read
            ), array(
                'OrganisationNotification.organisation_id' => $organisation_id,
                'OrganisationNotification.id' => $notification_id
            ));
        }

        return array('status' => 'success', 'notification_id' => $notification_id, 'read' => $read);
    }

    public function markAllRead($organisation_id, $read = 1) {
        $this->updateAll(array(
            'OrganisationNotification.read' => $read
                ), array(
            'OrganisationNotification.organisation_id' => $organisation_id
        ));

        return array('status' => 'success', 'read' => $read);
    }

}
